﻿using AexoManager.Datos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AexoManager.BussinesLogic
{
    public class BSDespiece : BSParent
    {
        public Despiece ObtenerDespiece(Producto unProducto)
        {
            return ObtenerDespiece(unProducto, null);
        }

        public Despiece ObtenerDespiece(Producto unProducto, Parte unaParte)
        {
            Despiece root = new Despiece();
            try
            {
                List<ISPDespiece> resultado;
                if (unaParte == null)
                    resultado = context().DespieceConsultar(unProducto);
                else
                    resultado = context().DespieceConsultar(unProducto, unaParte);

                var listRoot = resultado.Last().Jerarquia.Split('/').ToList();
                int countParseRoot = listRoot.Count();
                listRoot.RemoveAt(listRoot.Count - 2);
                string jerarquiaRoot = listRoot.Aggregate((i, j) => i + "/" + j);

                root.Child = new List<Despiece>();
                short? nivelAnterior = 99;
                List<Despiece> hijos = new List<Despiece>();
                Dictionary<string, List<Despiece>> diccionario = new Dictionary<string, List<Despiece>>();

                string padreAnterior = "";
                List<string> arrPadreAnterior = new List<string>();
                foreach (var item in resultado)
                {
                    var arrPadre = item.Jerarquia.Split('/').ToList();
                    arrPadre.RemoveAt(arrPadre.Count - 2);

                    string jerarquiaActual = item.Jerarquia.Replace("/", "");
                    /**/
                    string padre = "";
                    var listTemp = item.Jerarquia.Split('/').ToList();
                    listTemp.RemoveAt(listTemp.Count - 2);
                    padre = listTemp.Aggregate((i, j) => i + "/" + j);
                    /**/

                    if (padre != jerarquiaRoot)
                    {
                        Parte unaParteDesc = context().ParteGet(item.IdParte);
                        Despiece unDespiece = new Despiece();
                        unDespiece.Parte = new Parte { IdParte = item.IdParte, Descripcion = unaParteDesc.Descripcion };
                        unDespiece.Producto = new Producto { IdProducto = item.IdProducto };
                        unDespiece.Cantidad = (int)item.Cantidad;
                        unDespiece.EsInsumo = (item.EsInsumo == 1) ? true : false;

                        //if (padre != padreAnterior)
                        if (!arrPadre.SequenceEqual(arrPadreAnterior))
                        {
                            if (arrPadre.Count == countParseRoot)
                            {
                                unDespiece.Child = hijos;
                                hijos = new List<Despiece>();
                                root.Child.Add(unDespiece);
                            }
                            else
                            {
                                //unDespiece.Child = hijos;
                                var rar = diccionario.Where(x => x.Key == jerarquiaActual).ToList();
                                if (rar.Count != 0)
                                {
                                    unDespiece.Child = diccionario[jerarquiaActual];
                                    var rar2 = diccionario.Where(x => x.Key == Despiece.ArmarPadre(arrPadre)).ToList();
                                    if (rar2.Count != 0)
                                    {
                                        hijos = diccionario[Despiece.ArmarPadre(arrPadre)];
                                        hijos.Add(unDespiece);
                                        diccionario[Despiece.ArmarPadre(arrPadre)] = hijos;
                                    }
                                    else
                                    {
                                        hijos = new List<Despiece>();
                                        hijos.Add(unDespiece);
                                        diccionario.Add(Despiece.ArmarPadre(arrPadre), hijos);
                                    }
                                }
                                else
                                {
                                    hijos = new List<Despiece>();
                                    hijos.Add(unDespiece);
                                    diccionario.Add(Despiece.ArmarPadre(arrPadre), hijos);
                                }
                            }

                        }
                        else
                        {
                            if (arrPadre.Count == countParseRoot)
                            {
                                unDespiece.Child = hijos;
                                hijos = new List<Despiece>();
                                root.Child.Add(unDespiece);
                            }
                            else
                            {
                                var rar = diccionario.Where(x => x.Key == Despiece.ArmarPadre(arrPadre)).ToList();
                                if (rar.Count != 0)
                                {
                                    hijos = diccionario[Despiece.ArmarPadre(arrPadre)];
                                    hijos.Add(unDespiece);
                                    diccionario[Despiece.ArmarPadre(arrPadre)] = hijos;
                                }
                                else
                                {
                                    //hijos = diccionario[Despiece.ArmarPadre(arrPadre)];
                                    hijos.Add(unDespiece);
                                    diccionario.Add(Despiece.ArmarPadre(arrPadre), hijos);
                                    //hijos.Add(unDespiece);
                                }
                            }

                        }
                    }
                    else
                    {
                        Parte unaParteDesc = context().ParteGet(item.IdParte);
                        root.Parte = new Parte { IdParte = item.IdParte, Descripcion = unaParteDesc.Descripcion };
                        root.Producto = new Producto { IdProducto = item.IdProducto };
                        root.Cantidad = (int)item.Cantidad;
                        root.EsInsumo = (item.EsInsumo == 1) ? true : false;
                    }

                    padreAnterior = padre;
                    arrPadreAnterior = arrPadre;
                    nivelAnterior = item.Nivel;

                }
            }
            catch (Exception)
            {
                throw;
            }
            return root;

        }

        public IList<Despiece> ObtenerHijos(Producto unProducto, Parte unaParte)
        {
            try
            {
                return context().DespieceConsultarHijos(unProducto, unaParte);
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// Guarda una Parte con todos sus hijos como Insumo (en la tabla de insumo) Para ser utilizado en el despiece
        /// como una parte compuesta.
        /// </summary>
        /// <param name="unProducto"></param>
        /// <param name="unaParte"></param>
        public void SaveNuevoInsumo(Producto unProducto, Parte unaParte)
        {
            try
            {
                List<ISPDespiece> listaPartes;
                listaPartes = context().DespieceConsultar(unProducto, unaParte);
                var listaDespiece = listaPartes.OrderBy(x => x.Nivel).Select(j => new Insumo
                {
                    Parte = new Parte { IdParte = j.IdParte },
                    Cantidad  = j.Cantidad
                });

                foreach (var item in listaDespiece)
                {
                    context().InsumoAgregar(item, new Parte
                    {
                        IdParte = (int) listaPartes.Where(x => x.IdParte == item.Parte.IdParte).FirstOrDefault().IdPartePadre
                    });

                }
                context().Commit();
            }
            catch (Exception)
            {
                throw;
            }

        }

        public void SaveHijo(Despiece unDespiece, int idParte)
        {
            try
            {
                context().DespieceAgregarHijo(unDespiece, new Parte { IdParte = idParte });
                context().Commit();
            }
            catch (Exception)
            {
                throw;
            }
        }


        public void SaveRoot(Despiece unDespiece)
        {
            try
            {
                context().DespieceAgregarRoot(unDespiece);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
